/**********************************************************************\

 Copyright 2012 Diggory Blake

 This file is part of klip-engine

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

\**********************************************************************/
#pragma once

#define NOMINMAX
#include <Windows.h>
#include <set>

#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "opengl32.lib")

class kWindowWindows;
class kSystemWindows;

#ifndef _tWinMain
#ifdef UNICODE
#define _tWinMain   wWinMain
#else
#define _tWinMain   WinMain
#endif
#endif

#ifndef KLIP_SYSTEM_DEFAULT
#define KLIP_SYSTEM_DEFAULT
#define KLIP_MAIN() APIENTRY _tWinMain(HINSTANCE _unused0, HINSTANCE _unused1, LPTSTR _unused2, int _unused3)
typedef kSystemWindows kSystemDefault;
#endif

#include "ksystem.h"
#include "kewindowoptions.h"

class kWindowWindows : public kWindow {
	friend class kSystemWindows;
private:
	HWND _hwnd;
	keWindowOptions _options;
	kBasicMouseInput _mouseInput;
	kBasicKeyboardInput _keyboardInput;
	static std::set<kWindowWindows*> _windows;

	inline kWindowWindows() {
		_hwnd = 0;
		_options = keWindow_None;
		_windows.insert(this);
		_mouseInput.setSender(this);
		_keyboardInput.setSender(this);
	}
	void update();

public:
	~kWindowWindows() {
		_windows.erase(this);
	}

	virtual kHandle getHandle();
	virtual kMouseInput* getMouseInput();
	virtual kKeyboardInput* getKeyboardInput();

	virtual void close();
	virtual void destroy();
	virtual kHandle createGLContext();
	virtual void deleteGLContext(kHandle context);
	virtual void activateGLContext(kHandle context);
	virtual void setOptions(keWindowOptions options);
	virtual void setSize(const kVec2i& size);
	virtual void setPos(const kVec2i& pos);
	virtual void setTitle(const std::tstring& title);
	virtual void swapGLBuffers();
	virtual kVec2i getPos();
	virtual kVec2i getSize();
	virtual keWindowOptions getOptions();
};

class kSystemWindows : public kSystem {
	friend class kWindowWindows;
private:
	static ATOM _windowClass;
	static LRESULT CALLBACK staticWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
	static DWORD getWindowStyle(keWindowOptions options);
	static DWORD getWindowStyleEx(keWindowOptions options);

protected:
	virtual void onUpdate(float delta);

public:

	inline kSystemWindows() {};
	virtual unsigned getTime();
	virtual kWindow* createWindow(const std::tstring& title);
};
